home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Ham Radio 2000
/
Ham Radio 2000.iso
/
ham2000
/
tcp_ip
/
ethrax25
/
ax25util.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-05-30
|
9KB
|
306 lines
/*
** AX25UTIL.C - utility routines for Ether to AX.25 packet driver
** Copyright (C) 1994 Gary L. Grebus
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; version 2.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
**
**
** Utilities for handling AX.25 addresses encoded into a form that
** resembles an Ethernet address.
**
** An AX.25 address consists of 7 octets in the "shifted" form described
** in the AX.25 spec.
**
** The psuedo-Ethernet form consists six bytes:
** The low order byte is contains the SSID, in the AX.25 left-shifted
** form (this insures the address is not a broadcast address).
** The next two bytes contain the first two bytes of the AX.25
** address in AX.25 left-shifted from.
** The last 3 bytes contain the final 4 bytes AX.25 address ,
** encoded using 6 bit characters (0-9, blank, A-Z).
**
** The AX.25 address QST-0 is interpreted as the broadcast address and
** is converted to the pseudo-ethernet address FF-FF-FF-FF-FF-FF, and
** vice versa.
**
** Original version:
** 7 April 1994 - Gary L. Grebus, K8LT, glg@k8lt.ampr.org
*/
#ifndef DRIVER
#include <ctype.h>
#include <stdlib.h>
#endif
#define ARP_REQUEST 0x0100 /* ARP request opcode */
#define ARP_REPLY 0x0200 /* ARP reply opcode */
#include "ax25util.h"
#define SSID 0x1e /* Mask for SSID bits in AX.25 addr */
typedef struct _AX25Arp {
int hardware; /* Hardware type */
int protocol; /* Protocol type */
char hwalen; /* Hardware addr length in bytes */
char pralen; /* Protocol addr length in bytes */
int opcode; /* ARP opcode */
unsigned char shwaddr[AXALEN]; /* Sender hardware address */
long sprotoaddr; /* Sender protocol address */
unsigned char thwaddr[AXALEN]; /* Target hardware address */
long tprotoaddr; /* Target protocol address */
} AX25Arp;
typedef struct _EtherArp {
int hardware; /* Hardware type */
int protocol; /* Protocol type */
char hwalen; /* Hardware addr length in bytes */
char pralen; /* Protocol addr length in bytes */
int opcode; /* ARP opcode */
char shwaddr[PSEUDOLEN]; /* Sender hardware address */
long sprotoaddr; /* Sender protocol address */
char thwaddr[PSEUDOLEN]; /* Target hardware address */
long tprotoaddr; /* Target protocol address */
} EtherArp;
char qst[] = { 'Q'<<1, 'S'<<1, 'T'<<1, ' '<<1, ' '<<1, ' '<<1, '\0'<<1 };
/* A six-bit encoding of the AX.25 characters: 0-9, A-Z, space */
/* Invalid characters mapped to 63 */
unsigned char sixbit[] = {
37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
36,37,37,37,37,37,37,37,37,37,37,37,37,37,37,37,
0,1,2,3,4,5,6,7,8,9,37,37,37,37,37,37,
37,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,
25,26,27,28,29,30,31,32,33,34,35,37,37,37,37,37};
unsigned char eightbit[] = {
'0'<<1, '1'<<1, '2'<<1, '3'<<1, '4'<<1, '5'<<1, '6'<<1, '7'<<1,
'8'<<1, '9'<<1,
'A'<<1, 'B'<<1, 'C'<<1, 'D'<<1, 'E'<<1, 'F'<<1, 'G'<<1, 'H'<<1,
'I'<<1, 'J'<<1, 'K'<<1, 'L'<<1, 'M'<<1, 'N'<<1, 'O'<<1, 'P'<<1,
'Q'<<1, 'R'<<1, 'S'<<1, 'T'<<1, 'U'<<1, 'V'<<1, 'W'<<1, 'X'<<1,
'Y'<<1, 'Z'<<1, ' '<<1, '?'<<1 };
/* Routine to convert an ARP packet containing AX.25 addresses to the
* equivalent packet containing pseudo-Ethernet addresses.
* Since the packet will shrink, do the conversion such that it could be
* happening in-place.
*/
void
AArpToEArp(AX25Arp far *a_arp, EtherArp far *e_arp)
{
int i;
e_arp->hardware = 0x0100;
e_arp->protocol = 0x0008;
e_arp->hwalen = 6;
e_arp->pralen = 4;
e_arp->opcode = a_arp->opcode;
a_arp->shwaddr[6] &= SSID; /* Turn off any AX.25 control bits */
AX25ToEther(&(a_arp->shwaddr[0]), (ether_t *)&(e_arp->shwaddr[0]));
e_arp->sprotoaddr = a_arp->sprotoaddr;
if( a_arp->opcode == ARP_REPLY ) {
a_arp->thwaddr[6] &= SSID; /* Turn off any AX.25 control bits */
AX25ToEther(&(a_arp->thwaddr[0]), (ether_t *)&(e_arp->thwaddr[0]));
} else {
for( i = 0; i < PSEUDOLEN; i++)
e_arp->thwaddr[i] = '\0';
}
e_arp->tprotoaddr = a_arp->tprotoaddr;
}
/* Convert an AX.25 address in network form into a pseudo-ethernet address */
void
AX25ToEther(unsigned char far *ax25, ether_t *ether)
{
register int i;
for(i = 0; i < AXALEN; i++) {
if( ax25[i] != qst[i] )
break;
}
if (i == AXALEN) {
for( i = 0; i < PSEUDOLEN; i++)
*ether++ = (unsigned char)0xff;
return;
}
/* Do this in reverse order to allow the source and destination
* to be the same buffer.
*/
ether[5] = (sixbit[ ax25[4] >> 1 ] << 6) |
sixbit[ ax25[5] >> 1 ];
ether[4] = (sixbit[ ax25[3] >> 1 ] << 4) |
(sixbit[ ax25[4] >> 1 ] >> 2);
ether[3] = (sixbit[ ax25[2] >> 1 ] << 2) |
(sixbit[ ax25[3] >> 1 ] >> 4);
ether[2] = ax25[1];
ether[1] = ax25[0];
ether[0] = ax25[6] & SSID;
}
/* Routine to convert an ARP packet containing pseudo-Ethernet addresses
* to the equivalent packet containing AX.25 addresses.
*
* This routine assumes that the constant fields of the AX.25 ARP packet
* have been statically initialized.
*/
void
EArpToAArp(EtherArp far *e_arp, AX25Arp *a_arp)
{
int i;
a_arp->opcode = e_arp->opcode;
EtherToAX25((ether_t *)&(e_arp->shwaddr[0]), &(a_arp->shwaddr[0]));
a_arp->sprotoaddr = e_arp->sprotoaddr;
if( e_arp->opcode == ARP_REPLY )
EtherToAX25((ether_t *)&(e_arp->thwaddr[0]), &(a_arp->thwaddr[0]));
else {
for( i = 0; i < AXALEN; i++)
a_arp->thwaddr[i] = '\0';
}
a_arp->tprotoaddr = e_arp->tprotoaddr;
}
/* Convert a pseudo-Ethernet address to an AX.25 address in network form */
void
EtherToAX25(ether_t *ether, unsigned char *ax25)
{
register int i;
for (i = 0; i < PSEUDOLEN; i++) {
if( ether[i] != (unsigned char)0xff )
break;
}
if( i == PSEUDOLEN ) {
for( i = 0; i < AXALEN; i++)
*ax25++ = qst[i];
return;
}
ax25[0] = ether[1];
ax25[1] = ether[2];
ax25[2] = eightbit[ ether[3] >> 2 ];
ax25[3] = eightbit[ ((ether[3] & 0x3) << 4) | (ether[4] >> 4) ];
ax25[4] = eightbit[ ((ether[4] & 0xf ) << 2) | (ether[5] >> 6) ];
ax25[5] = eightbit[ ether[5] & 0x3f ];
ax25[6] = ether[0];
}
#ifndef DRIVER
/* Convert an AX.25 address in null terminated string into network form */
void
StrToAX25(char *s, unsigned char *ax25)
{
unsigned char *axp = &ax25[0];
while(*s != '\0' && *s != '-') {
*axp++ = toupper(*s) << 1;
s++;
}
while( axp < &ax25[6] )
*axp++ = ' ' << 1;
if( *s++ == '-')
*axp = atoi(s) << 1;
else
*axp = '\0';
}
/* Convert an AX.25 address in network form into a null terminated string */
void
AX25ToStr(unsigned char *ax25, char *s)
{
int i;
for( i = 0; i < 6; i++) {
if( (*ax25 >> 1) != ' ')
*s++ = *ax25 >> 1;
ax25++;
}
if( *ax25 != '\0' ) {
*s++ = '-';
(void)itoa(*ax25 >> 1, s, 10);
} else
*s = '\0';
}
#endif
#undef TEST
#ifdef TEST
#include <stdio.h>
main(int argc, char **argv)
{
char c;
unsigned char ax25[7];
unsigned char ether[6];
char callsign[8];
int i;
while( 1 ) {
printf("[A]X.25 or [E]thernet?: ");
scanf(" %c", &c);
if( c == 'A' ) {
/* Pervert the callsign into AX.25 form including shift */
scanf(" %s", callsign);
StrToAX25(callsign, ax25);
/* Translate, and translate back */
AX25ToEther(ax25, ether);
for( i = 0; i < 5; i++)
printf("%02x-", ether[i]);
printf("%02x\n", ether[5]);
EtherToAX25(ether, ax25);
AX25ToStr(ax25, callsign);
printf("%s\n", callsign);
} else {
scanf(" %x-%x-%x-%x-%x-%x", ðer[0], ðer[1], ðer[2],
ðer[3], ðer[4], ðer[5]);
/* Translate, and translate back */
EtherToAX25(ether, ax25);
for(i = 0; i < 6; i++)
printf("%c", ax25[i]>>1);
printf("-%d\n", ax25[6]>>1);
AX25ToEther(ax25, ether);
for( i = 0; i < 5; i++)
printf("%02x-", ether[i]);
printf("%02x\n", ether[5]);
}
}
}
#endif